package com.cd.form.api.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.cd.common.util.AuthUtils;
import com.cd.common.util.StatsReportExcelUtils;
import com.cd.form.api.FormService;
import com.cd.form.jpa.domian.FormAuth;
import com.cd.form.jpa.domian.FormComponent;
import com.cd.form.jpa.domian.FormInstance;
import com.cd.form.jpa.domian.FormResult;
import com.cd.form.jpa.repo.FormAuthRepository;
import com.cd.form.jpa.repo.FormComponentRepo;
import com.cd.form.jpa.repo.FormInstanceRepo;
import com.cd.form.jpa.repo.FormResultRepo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class FormServiceImpl implements FormService {

    @Autowired
    private FormComponentRepo formComponentRepo;

    @Autowired
    private FormResultRepo formResultRepo;

    @Autowired
    private FormInstanceRepo formInstanceRepo;

    @Autowired
    private FormAuthRepository formAuthRepository;

    @Override
    public List<FormComponent> getFormComponentByFormId(Long formId) {
        List<FormComponent> byFormId = formComponentRepo.findByFormId(formId);
        //按照order的顺序进行正序排序
        byFormId.sort((o1, o2) -> o1.getOrder() - o2.getOrder());
        return byFormId;
    }

    @Override
    public void submitForm(FormResult formResult) {
        formResult.setCreateTime(new Date());
        formResult.setUserId(AuthUtils.currentUserId());
        if (!formInstanceRepo.findByFormId(formResult.getFormId()).get().getIsApproval()) {
            formResult.setStatus(3);
        }
        formResultRepo.save(formResult);
    }

    @Override
    public FormInstance getFormInfo(Long formId) {
        Optional<FormInstance> byFormId = formInstanceRepo.findByFormId(formId);
        if (byFormId.isPresent()) {
            return byFormId.get();
        }
        return null;
        //return formInstanceRepo.findByFormId(formId);
    }

    /**
     * 获取表单结果
     *
     * @param formId
     * @return
     */
    @Override
    public List<FormResult> getFormResult(Long formId) {
        Long userId=AuthUtils.currentUserId();
        Boolean isResultVisible = formInstanceRepo.findByFormId(formId).get().getIsResultVisible();
        List<FormResult> data =null;
        //admin可无限制查看 权限用户可无限制查看 普通用户可在展示情况下查看部分数据 其他数据无法查看
        if (AuthUtils.isAdmin(userId) || formAuthRepository.existsById_FormIdAndId_UserId(formId, userId)) {
            data = formResultRepo.findByFormId(formId);
            return data;
        }
        if (isResultVisible) {//非权限用户 则只能查看已通过的 或无需审批的 1和3
            data = formResultRepo.findByFormId(formId);
            return data.stream().filter(a -> a.getStatus() == 1 || a.getStatus() == 3).collect(Collectors.toList());
        }
        throw new RuntimeException("抱歉，您无权限访问");
        //return data;
    }

    /**
     * 有条件获取表单结果
     *
     * @param formId
     * @param status
     * @return
     */
    @Override
    public List<FormResult> getFormResultWithStatus(Long formId, Integer status) {
        checkAuth(formId, AuthUtils.currentUserId());
        List<FormResult> data = formResultRepo.findByFormIdAndStatus(formId, status);
        return data;
    }

    @Override
    public void updateStatus(FormResult formResult) {
        //校验是否有审批权限
        Long formId = formResultRepo.findById(formResult.getResultId()).get().getFormId();
        if (!formAuthRepository.existsById_FormIdAndId_UserId(formId, AuthUtils.currentUserId())) {
            throw new RuntimeException("抱歉，您无权限访问");
        }
        int i = formResultRepo.updateStatusByResultId(formResult.getStatus(), formResult.getResultId());
        if (i != 1) {
            throw new RuntimeException("修改失败");
        }
    }

    @Override
    public List<FormInstance> getFormInstance(Long formId, String name) {
        //如果不是超级管理员 则获取权限
        Long userId = AuthUtils.currentUserId();
        if (AuthUtils.isAdmin(userId)) {
            if (name != null) {
                return formInstanceRepo.findByNameLike(name);
            }
            return formInstanceRepo.findAll();

        } else {

            List<FormAuth> byFormId = formAuthRepository.findById_UserId(userId);
            List<Long> formIdList = byFormId.stream().map(FormAuth::getFormId).collect(Collectors.toList());
            List<FormInstance> byFormIdIn = formInstanceRepo.findByFormIdIn(formIdList);
            if (name != null) {
                return byFormIdIn.stream().filter(formInstance -> formInstance.getName().contains(name)).collect(Collectors.toList());
            }
            return byFormIdIn;
        }
    }

    @Override
    public void createFormInstance(FormInstance formInstance) {

        if (formInstance.getFormId() != null) {
            throw new RuntimeException("表单实例已经存在");
        }
        FormInstance save = formInstanceRepo.save(formInstance);
        //权限添加
        FormAuth formAuth = new FormAuth();
        formAuth.setFormId(save.getFormId());
        formAuth.setUserId(AuthUtils.currentUserId());
        formAuthRepository.save(formAuth);
    }

    @Override
    public void updateFormInstance(FormInstance formInstance) {
        if (formInstance.getFormId() == null) {
            throw new RuntimeException("表单需要有id");
        }
        //权限校验
        checkAuth(formInstance.getFormId(), AuthUtils.currentUserId());
        formInstanceRepo.save(formInstance);
    }

    @Override
    public void updateFormComponentBatch(List<FormComponent> formComponents) {
        //检查列表中的实例的form_id属性是否一致
        checkFormId(formComponents);

        Long formId = formComponents.get(0).getFormId();
        //权限校验
        checkAuth(formId, AuthUtils.currentUserId());
        formComponentRepo.saveAll(formComponents);
    }

    @Override
    public void createFormComponent(FormComponent formComponent) {
        checkAuth(formComponent.getFormId(), AuthUtils.currentUserId());
        if (formComponent.getId() != null) {
            throw new RuntimeException("表单组件已经存在");
        }
        formComponentRepo.save(formComponent);
    }

    @Override
    public void updateFormComponent(FormComponent formComponent) {
        checkAuth(formComponent.getFormId(), AuthUtils.currentUserId());
        if (formComponent.getId() == null) {
            throw new RuntimeException("更新表单组件需要有id");
        }
        formComponentRepo.save(formComponent);
    }

    @Override
    public void removeFormComponent(Long formComponentId) {
        checkAuth(formComponentId, AuthUtils.currentUserId());
        formComponentRepo.deleteById(formComponentId);
    }

    @Override
    public void copyFormComponent(Long fromFormId, Long currentFromId) {
        //权限检查
        checkAuth(currentFromId, AuthUtils.currentUserId());

        //check currentFrom is exist
        Optional<FormInstance> byFormId = formInstanceRepo.findByFormId(currentFromId);
        if (!byFormId.isPresent()) {
            throw new RuntimeException("需要拷贝的目标表单实例不存在");
        }

        //被拷贝表单组件获取
        List<FormComponent> fromFormComponents = formComponentRepo.findByFormId(fromFormId);
        fromFormComponents.stream().forEach(formComponent -> {
            formComponent.setId(null);
            formComponent.setFormId(currentFromId);
        });

        formComponentRepo.saveAll(fromFormComponents);

    }

    @Override
    public void excelImport(Long formId, HttpServletResponse response) {
        if (formId == null) {
            throw new RuntimeException("表单需要有id");
        }

        // 1. 获取表单组件作为表头
        List<FormComponent> byFormId = formComponentRepo.findByFormId(formId);
        Map<String, Object> titles = new LinkedHashMap<>();
        //按照order属性排序
        byFormId.sort((o1, o2) -> o1.getOrder() - o2.getOrder());
        byFormId.forEach(formComponent -> {
            titles.put(formComponent.getName(), formComponent.getName());
        });
        titles.put("createTime", "填写时间");
        titles.put("status", "状态");

        // 2. 获取表单结果数据
        List<FormResult> data = formResultRepo.findByFormId(formId);
        List<HashMap<String, Object>> result = new ArrayList<>();

        // 3. 解析每个结果的data字段
        for (FormResult formResult : data) {
            HashMap<String, Object> rowData = new LinkedHashMap<>();

            try {
                // 使用Fastjson解析JSON数组
                List<Map<String, Object>> fieldValues = JSON.parseObject(
                        formResult.getData(),
                        new TypeReference<List<Map<String, Object>>>() {}
                );

                // 将字段值按name映射到行数据
                for (Map<String, Object> field : fieldValues) {
                    String name = (String) field.get("name");
                    Object value = field.get("value");
                    rowData.put(name, value != null ? value : "");
                }

                // 添加创建时间
                rowData.put("createTime", formResult.getCreateTime());
                rowData.put("status", covertStatusToCHN(formResult.getStatus()));

                result.add(rowData);
            } catch (Exception e) {
                throw new RuntimeException("解析表单数据失败: " + e.getMessage(), e);
            }
        }

        // 4. 导出Excel
        try {
            StatsReportExcelUtils.export(response, titles, result, "表单数据导出");
        } catch (Exception e) {
            throw new RuntimeException("导出Excel失败: " + e.getMessage(), e);
        }
    }

    private String covertStatusToCHN(Integer status) {
        //0:待审批 1:通过 2:拒绝 3:无需审批
        switch (status) {
            case 0:
                return "待审批";
            case 1:
                return "通过";
            case 2:
                return "拒绝";
            default:
                return "无需审批";
        }
    }

    private void checkFormId(List<FormComponent> formComponents) {
        if (formComponents.size() > 0) {
            Long formId = formComponents.get(0).getFormId();
            for (FormComponent formComponent : formComponents) {
                if (!formComponent.getFormId().equals(formId)) {
                    throw new RuntimeException("表单实例的form_id属性不一致");
                }
            }
        }
    }

    //权限检查
    private void checkAuth(Long formId, Long userId) {
        Boolean isResultVisible = formInstanceRepo.findByFormId(formId).get().getIsResultVisible();
        if (AuthUtils.isAdmin(userId) || isResultVisible) {
            return;
        }
        if (!formAuthRepository.existsById_FormIdAndId_UserId(formId, userId)) {
            throw new RuntimeException("抱歉，您无权限访问");
        }
    }
}
